package com.weacar.weixin.util.sms;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.weacar.weixin.service.InternalServiceException;
import com.weacar.weixin.util.HttpClientUtils;
import com.weacar.weixin.util.LogUtils;
import com.weacar.weixin.util.sms.dao.SmsMessageDao;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author Fong
 */
@Service
public class YunpianSmsWrapper extends SmsService {
    private static final Logger LOG = LoggerFactory.getLogger(SmsService.class);

    private static String URI_SEND_SMS = "http://yunpian.com/v1/sms/send.json";

    @Value("${weacar.sms.yunpian.apikey:1251f5289e3d8894dc377158c3137684}")
    private String API_KEY;

    @Value("${weacar.sms.template:【网车网】您的验证码是#code#}")
    private String TEMPLATE;


    @Autowired
    private SmsMessageDao smsMessageDao;

    private HttpClientUtils httpClientUtils = new HttpClientUtils();

    @Transactional
    @Override
    public void sendSmsCode(String fromUserName, String mobile) throws SmsServiceException {
        String code = generateCode();
        Date now = new Date();
        SmsMessage smsMessage = new SmsMessage();
        smsMessage.setUserName(fromUserName);
        smsMessage.setSendTo(mobile);
        smsMessage.setCode(code);
        smsMessage.setText(TEMPLATE.replace("#code#", code));
        smsMessage.setExpiredAt(DateUtils.addMinutes(now, 30));
        smsMessage.setSendAt(now);
        try {
            smsMessageDao.save(smsMessage);
        } catch (Exception e) {
            LOG.error("sendSmsCode(mobile) error : " + mobile, e);
            throw new InternalServiceException(e.getMessage());
        }
        String responseString = send(smsMessage);
        if (StringUtils.isBlank(responseString)) {
            throw new SmsServiceException("Call yunpian API response blank!");
        }
        Gson gson = new GsonBuilder().create();
        Map map = gson.fromJson(responseString, HashMap.class);
        Double ypCode = (Double)map.get("code");
        if (ypCode != 0) {
            throw new SmsServiceException("Yunpian API return code: " + ypCode);
        }
    }


    @Override
    public boolean isSmsCodeValid(String fromUserName, String mobile, String code) {
        try {
            SmsMessage message = smsMessageDao.queryByCode(fromUserName, mobile, code);
            if (message != null && StringUtils.equals(message.getCode(), code)) {
                return true;
            }
            return false;
        } catch (Exception e) {
            LOG.error("isSmsCodeValid(mobile, code) error : mobile=" + mobile + ", code=" + code, e);
            throw new InternalServiceException(e.getMessage());
        }
    }

    @Override
    public void sendText(String mobile, String text) throws SmsServiceException {
        Date now = new Date();
        SmsMessage smsMessage = new SmsMessage();
        smsMessage.setSendTo(mobile);
        smsMessage.setText(text);
        smsMessage.setSendAt(now);
        try {
            smsMessageDao.save(smsMessage);
        } catch (Exception e) {
            LogUtils.errorException(LOG, null, e);
            throw new InternalServiceException();
        }
        String responseString = send(smsMessage);
        if (StringUtils.isBlank(responseString)) {
            throw new SmsServiceException("Call yunpian API response blank!");
        }
        Gson gson = new GsonBuilder().create();
        Map map = gson.fromJson(responseString, HashMap.class);
        Double ypCode = (Double)map.get("code");
        if (ypCode != 0) {
            throw new SmsServiceException("Yunpian API return code: " + ypCode);
        }
    }


    private String send(SmsMessage smsMessage) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("apikey", API_KEY);
        params.put("text", smsMessage.getText());
        params.put("mobile", smsMessage.getSendTo());
        String responseString = httpClientUtils.httpPost(URI_SEND_SMS, params);
        LOG.debug("send(SmsMessage) : " + responseString);
        return responseString;
    }



    private String generateCode() {
        Integer code = ThreadLocalRandom.current().nextInt(100000, 999999);
        return code.toString();
    }
}
